package org.jing.ext.security;

import org.jing.core.lang.JingException;
import org.jing.core.util.StringUtil;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2021-03-03 <br>
 */
public class MD5 {
    private static final int DEFAULT_BUFFER_SIZE = 1024;

    private static final boolean DEFAULT_TO_UPPER_CASE = false;

    private static final String DEFAULT_ENCODING = "utf-8";

    public static String encrypt(InputStream inputStream, boolean toUpperCase, int bufferSize) {
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            byte[] buffer = new byte[bufferSize];
            int index;
            while ((index = inputStream.read(buffer, 0, bufferSize)) != -1) {
                messageDigest.update(buffer, 0, index);
            }
            String md5 = new BigInteger(1, messageDigest.digest()).toString(16);
            return toUpperCase ? md5.toUpperCase() : md5.toLowerCase();
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t, "Failed to calculate md5");
        }
    }

    public static String encrypt(String content, String encoding, boolean toUpperCase, int bufferSize) {
        encoding = StringUtil.ifEmpty(encoding, DEFAULT_ENCODING);
        try (ByteArrayInputStream reader = new ByteArrayInputStream(content.getBytes(encoding))) {
            return encrypt(reader, toUpperCase, bufferSize);
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t, "Failed to calculate md5");
        }
    }

    public static String encrypt(String content, String encoding, boolean toUpperCase) {
        return encrypt(content, encoding, toUpperCase, DEFAULT_BUFFER_SIZE);
    }

    public static String encrypt(String content, String encoding, int bufferSize) {
        return encrypt(content, encoding, DEFAULT_TO_UPPER_CASE, bufferSize);
    }

    public static String encrypt(String content, boolean toUpperCase, int bufferSize) {
        return encrypt(content, DEFAULT_ENCODING, toUpperCase, bufferSize);
    }

    public static String encrypt(String content, int bufferSize) {
        return encrypt(content, DEFAULT_ENCODING, DEFAULT_TO_UPPER_CASE, bufferSize);
    }

    public static String encrypt(String content, boolean toUpperCase) {
        return encrypt(content, DEFAULT_ENCODING, toUpperCase, DEFAULT_BUFFER_SIZE);
    }

    public static String encrypt(String content, String encoding) {
        return encrypt(content, encoding, DEFAULT_TO_UPPER_CASE, DEFAULT_BUFFER_SIZE);
    }

    public static String encrypt(String content) {
        return encrypt(content, DEFAULT_ENCODING, DEFAULT_TO_UPPER_CASE, DEFAULT_BUFFER_SIZE);
    }

    public static String encrypt(File file, boolean toUpperCase, int bufferSize) {
        try (FileInputStream reader = new FileInputStream(file)) {
            return encrypt(reader, toUpperCase, bufferSize);
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t, "Failed to calculate md5");
        }
    }

    public static String encrypt(File file, boolean toUpperCase) {
        return encrypt(file, toUpperCase, DEFAULT_BUFFER_SIZE);
    }

    public static String encrypt(File file, int bufferSize) {
        return encrypt(file, DEFAULT_TO_UPPER_CASE, bufferSize);
    }

    public static String encrypt(File file) {
        return encrypt(file, DEFAULT_TO_UPPER_CASE, DEFAULT_BUFFER_SIZE);
    }
}
